home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / game / think / UChesSrc.lha / search.c < prev    next >
C/C++ Source or Header  |  1993-06-03  |  37KB  |  1,489 lines

  1. /*
  2.  * search.c - C source for GNU CHESS
  3.  *
  4.  * Copyright (c) 1988,1989,1990 John Stanback Copyright (c) 1992 Free Software
  5.  * Foundation
  6.  *
  7.  * This file is part of GNU CHESS.
  8.  *
  9.  * GNU Chess is free software; you can redistribute it and/or modify it under
  10.  * the terms of the GNU General Public License as published by the Free
  11.  * Software Foundation; either version 2, or (at your option) any later
  12.  * version.
  13.  *
  14.  * GNU Chess is distributed in the hope that it will be useful, but WITHOUT ANY
  15.  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  16.  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  17.  * details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License along with
  20.  * GNU Chess; see the file COPYING.  If not, write to the Free Software
  21.  * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  */
  23. #include "gnuchess.h"
  24. #ifdef QUIETBACKGROUND
  25. short background = 0;
  26.  
  27. #endif /* QUIETBACKGROUND */
  28. static short int DepthBeyond;
  29. unsigned short int PrVar[MAXDEPTH];
  30. extern short int ISZERO;
  31. extern char mvstr[4][6];
  32. extern short int recycle;
  33. extern int trying_again;
  34. #ifdef NULLMOVE
  35. short int null;         /* Null-move already made or not */
  36. short int PVari;        /* Is this the PV */
  37. #endif
  38. #ifdef DEBUG40
  39. extern int whichway;
  40. #endif
  41. #ifdef DEBUG
  42. unsigned short DBLINE[MAXDEPTH];
  43. struct leaf *dbptr;
  44.  
  45. #endif
  46. short int zwndw;
  47.  
  48. #include "ataks3.h"
  49.  
  50. #define __USE_SYSBASE
  51. #include <proto/exec.h>
  52.  
  53. extern int global_tmp_score;
  54. extern int previous_score;
  55. int Sdepth2=0;
  56. extern int MoveNowOK;
  57. extern int procpri;
  58. extern struct Process *myproc;
  59.  
  60.  
  61. int Castled[2]={0,0};
  62. int myEnPassant[2]={0,0};
  63.  
  64.  
  65.  
  66. inline short int repetition (void);
  67.  
  68.  
  69. #include "debug41.h"
  70. /* ............    MOVE GENERATION & SEARCH ROUTINES    .............. */
  71.  
  72. inline
  73. short int
  74. repetition ()
  75.  
  76. /*  Check for draw by threefold repetition.  */
  77.  
  78. {
  79.   register short i, c,cnt;
  80.   register unsigned short m;
  81.   short b[64];
  82.  
  83.   cnt = c = 0;
  84.   /* try to avoid work */
  85.   if (GameCnt > Game50 + 2)
  86.     {
  87. #if defined(NOMEMSET) || defined(MSDOS)
  88.       for (i = 0; i < 64; b[i++] = 0);
  89. #else
  90.       memset ((char *) b, 0, (unsigned long)sizeof (b));
  91. #endif /* NOMEMSET */
  92.       for (i = GameCnt; i >= Game50; i--)
  93.     {
  94.       m = GameList[i].gmove;
  95.       /* does piece exist on diff board? */
  96.       if (b[m & 0xff])
  97.         {
  98.           /* does diffs cancel out, piece back? */
  99.           if ((b[m >> 8] += b[m & 0xff]) == 0)
  100.         --c;
  101.           b[m & 0xff] = 0;
  102.         }
  103.       else
  104.         {
  105.           /* create diff */
  106.           ++c;
  107.           /* does diff cancel out another diff? */
  108.           if (!(b[m >> 8] -= (b[m & 0xff] = board[m & 0xff] +
  109.                   (color[m & 0xff] << 8))))
  110.         --c;;
  111.         }
  112.       /* if diff count is 0 we have a repetition */
  113.       if (c == 0)
  114.         if ((i ^ GameCnt) & 1)
  115.           cnt++;
  116.     }
  117.     }
  118.     return cnt;
  119. }
  120.  
  121. int plyscore, globalscore;
  122. int
  123. pick (short int p1, short int p2)
  124.  
  125. /*
  126.  * Find the best move in the tree between indexes p1 and p2. Swap the best
  127.  * move into the p1 element.
  128.  *
  129.  */
  130. {
  131.   register struct leaf *p, *q, *r, *k;
  132.   register s0;
  133.   struct leaf temp;
  134.  
  135.   k = p = &Tree[p1];
  136.   q = &Tree[p2];
  137.   s0 = p->score;
  138.   for (r = p + 1; r <= q; r++)
  139.     if ((r->score) > s0)
  140.       {
  141.     s0 = (r->score);
  142.     p = r;
  143.       }
  144.   if (p != k)
  145.     {
  146.       temp = *p;
  147.       *p = *k;
  148.       *k = temp;
  149.       return true;
  150.     }
  151.   return false;
  152. }
  153.  
  154. #ifdef DEBUG
  155. unsigned short trace[MAXDEPTH];
  156. char traceline[256];
  157. unsigned short tracelog[MAXDEPTH];
  158. int tracen = 0;
  159. int traceflag = 0;
  160. int traceply = 0;
  161. #endif
  162. int bookflag = false;
  163.  
  164. static int TCcount, TCleft;
  165. void
  166. SelectMove (short int side, short int iop)
  167.  
  168.  
  169. /*
  170.  * Select a move by calling function search() at progressively deeper ply
  171.  * until time is up or a mate or draw is reached. An alpha-beta window of
  172.  * -Awindow to +Bwindow points is set around the score returned from the
  173.  * previous iteration. If Sdepth != 0 then the program has correctly
  174.  * predicted the opponents move and the search will start at a depth of
  175.  * Sdepth+1 rather than a depth of 1.
  176.  */
  177.  
  178. {
  179.   static short int i, tempb, tempc, tempsf, tempst, xside, rpt;
  180.   static short int alpha, beta, score;
  181.   static struct GameRec *g;
  182.   int Jscore = 0;
  183.   int earlyflag;
  184.   char mystr[16];
  185. #ifdef DEBUG
  186.  
  187. if(debuglevel & (512|1024)){
  188.     char b[32];
  189.     short c1,c2,r1,r2;
  190. tracen=0;
  191. traceflag = false;
  192. traceply = 0;
  193. tracelog[0]=0;
  194. while(true){
  195.     printf("debug?");
  196.     gets(b);
  197.     if(b[0] == 'p')traceply = atoi(&b[1]);
  198.     else
  199.     if(b[0] == '\0')break;
  200.     else{
  201.         c1 = b[0] - 'a';
  202.               r1 = b[1] - '1';
  203.               c2 = b[2] - 'a';
  204.               r2 = b[3] - '1';
  205.               trace[++tracen] = (locn (r1, c1) << 8) | locn (r2, c2);
  206.     }
  207.     if(tracen == 0 && traceply >0)traceflag = true;
  208.     }
  209.     
  210. }
  211. #endif
  212.  
  213.   flag.timeout = false;
  214.   flag.back = flag.musttimeout = false;
  215.   xside = side ^ 1;
  216.   recycle = (GameCnt % rehash) - rehash;
  217.   /* if background mode set to infinite */
  218.   if (iop == 2)
  219.     {
  220.       (void)SetTaskPri((struct Task *)myproc,0);
  221.       ResponseTime = 9999999;
  222. #ifdef QUIETBACKGROUND
  223.       background = true;
  224. #endif /* QUIETBACKGROUND */
  225.     }
  226.   else
  227.     {
  228.       player = side;
  229.       if (TCflag)
  230.     {
  231.       TCcount = 0;
  232. #ifdef QUIETBACKGROUND
  233.       background = false;
  234. #endif /* QUIETBACKGROUND */
  235.       if (TimeControl.moves[side] < 1)
  236.         TimeControl.moves[side] = 1;
  237.       /* special case time per move specified */
  238.       if (flag.onemove)
  239.         {
  240.           ResponseTime = TimeControl.clock[side] - 100;
  241.           TCleft = 0;
  242.         }
  243.       else
  244.         {
  245.           /* calculate avg time per move remaining */
  246.           TimeControl.clock[side] += TCadd;
  247.  
  248.           ResponseTime = (TimeControl.clock[side]) / (((TimeControl.moves[side]) * 2) + 1);
  249.           TCleft = (int)ResponseTime / 3;
  250.           ResponseTime += TCadd/2;
  251.           if (TimeControl.moves[side] < 5)
  252.         TCcount = MAXTCCOUNTX - 1;
  253.         }
  254.       if (ResponseTime < 100)
  255.         {
  256.           ResponseTime = 100;
  257.           TCcount = MAXTCCOUNTX;
  258.         }
  259.       else if (ResponseTime < 200)
  260.         {
  261.           TCcount = MAXTCCOUNTX - 1;
  262.         }
  263.     }
  264.       else
  265.        {
  266. #ifdef QUIETBACKGROUND
  267.       background = false;
  268. #endif /* QUIETBACKGROUND */
  269.     ResponseTime = MaxResponseTime;
  270.        }
  271.       if (TCleft)
  272.     {
  273.       TCcount = ((int)((TimeControl.clock[side] - ResponseTime)) / 2) / TCleft;
  274.       if (TCcount > MAXTCCOUNTX)
  275.         TCcount = 0;
  276.       else
  277.         TCcount = MAXTCCOUNTX - TCcount;
  278.     }
  279.       else
  280.     TCcount = MAXTCCOUNTX;
  281.     }
  282.  
  283.   if (MoveNowOK)
  284.    {
  285.     thinking2 = 1; /* allow move now menu item to work */
  286.    }
  287.   else
  288.    {
  289.     thinking2 = 0; /* do not allow move now menu item to work */
  290.    }
  291.   ExtraTime = 0;
  292.   ExaminePosition ();
  293.   score = ScorePosition (side);
  294. #ifdef QUIETBACKGROUND
  295.   if (!background)
  296. #endif /* QUIETBACKGROUND */
  297.     ShowSidetoMove ();
  298. #ifdef notdef
  299.   if (TCflag && TCcount < MAXTCCOUNT)
  300.     if (score < SCORETIME)
  301.       {
  302.     ExtraTime += TCleft;
  303.     TCcount++;
  304.       }
  305. #endif
  306.  
  307. #ifdef QUIETBACKGROUND
  308.   if (!background)
  309. #endif /* QUIETBACKGROUND */
  310.     SearchStartStuff (side);
  311. #ifdef HISTORY
  312. #if defined(NOMEMSET) || defined(MSDOS)
  313.   for (i = 0; i < 32768; i++)
  314.     history[i] = 0;
  315. #else
  316.   memset ((unsigned char *) history, 0, (unsigned long)sizeof (history));
  317. #endif /* NOMEMSET */
  318. #endif
  319.   FROMsquare = TOsquare = -1;
  320.   PV = 0;
  321.   if (iop == 1)
  322.     hint = 0;
  323.   for (i = 0; i < MAXDEPTH; i++)
  324.     PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = 0;
  325.   /* set initial window for search */
  326.   alpha = score - ((computer == black) ? BAwindow : WAwindow);
  327.   beta = score + ((computer == black) ? BBwindow : WBwindow);
  328.   rpt = 0;
  329.   TrPnt[1] = 0;
  330.   root = &Tree[0];
  331.   MoveList (side, 1);
  332.   for (i = TrPnt[1]; i < TrPnt[2]; i++)
  333.     if (!pick (i, TrPnt[2] - 1))
  334.       break;
  335.   /* can I get a book move? */
  336.   if (flag.regularstart && Book)
  337.     {
  338.       flag.timeout = bookflag = OpeningBook (&hint, side);
  339.       if (TCflag)
  340.     ResponseTime += ResponseTime;
  341.     }
  342.   /* zero stats for hash table */
  343.   reminus = replus = 0;
  344.   GenCnt = NodeCnt = ETnodes = EvalNodes = HashCnt = FHashAdd = HashAdd = FHashCnt = THashCol = HashCol = 0;
  345.   globalscore = plyscore = score;
  346.   zwndw = 20;
  347.   trying_again = global_tmp_score = previous_score = 0;
  348. #include "debug4.h"
  349.   /********************* main loop ********************************/
  350.     Sdepth = (MaxSearchDepth<(MINDEPTH-1))?MaxSearchDepth:(MINDEPTH-1);
  351. /*printf("\n\n");*/
  352.   while (!flag.timeout)
  353.     {
  354. /*printf("time0 = %d et = %d SDepth = %d GameCnt = %d\n",time0, et,Sdepth,GameCnt);*/
  355. /*printf("ThinkAheadWorked = %d  ThinkAheadDepth = %d\n",ThinkAheadWorked,ThinkAheadDepth);*/
  356.       /* go down a level at a time */
  357.       Sdepth++;
  358. #ifdef NULLMOVE
  359.       null = 0;
  360.       PVari = 1;
  361. #endif
  362.       DepthBeyond = Sdepth + ((Sdepth == 1) ? 7 : 11);
  363.  
  364. #if !defined CHESSTOOL && !defined XBOARD
  365. #ifdef QUIETBACKGROUND
  366.       if (!background)
  367. #endif /* QUIETBACKGROUND */
  368.     ShowDepth (' ');
  369. #endif
  370.       /* search at this level returns score of PV */
  371.       score = search (side, 1, Sdepth, alpha, beta, PrVar, &rpt);
  372.       /* save PV as killer */
  373.       for (i = 1; i <= Sdepth; i++)
  374.     killr0[i] = PrVar[i];
  375.  
  376.       /* low search failure re-search with (-inf,score) limits  */
  377.       if (score < alpha)
  378.     {
  379. #if !defined CHESSTOOL && !defined XBOARD
  380.       reminus++;
  381. #ifdef QUIETBACKGROUND
  382.       if (!background)
  383. #endif /* QUIETBACKGROUND */
  384.         ShowDepth ('-');
  385. #endif
  386.       if (TCflag && TCcount < MAXTCCOUNTR)
  387.         {
  388.           TCcount = MAXTCCOUNTR - 1;
  389.           ExtraTime += (8 * TCleft);
  390.         }
  391.       score = search (side, 1, Sdepth, -9999, score, PrVar, &rpt);
  392.     }
  393.       /* high search failure re-search with (score, +inf) limits */
  394.       if (score > beta && !(root->flags & exact))
  395.     {
  396. #if !defined CHESSTOOL && !defined XBOARD
  397.       replus++;
  398. #ifdef QUIETBACKGROUND
  399.       if (!background)
  400. #endif /* QUIETBACKGROUND */
  401.         ShowDepth ('+');
  402. #endif
  403.       score = search (side, 1, Sdepth, score, 9999, PrVar, &rpt);
  404.     }
  405.       /**************** out of search ********************************************/
  406.       if ((flag.timeout)||(flag.musttimeout)||(flag.back))
  407.        earlyflag = true;
  408.       else
  409.        earlyflag = false;
  410.       if (flag.musttimeout || Sdepth >= MaxSearchDepth)
  411.        {
  412.     flag.timeout = true;
  413.        }
  414.       else if (TCflag && (Sdepth > (MINDEPTH - 1)) && (TCcount < MAXTCCOUNTR))
  415.     {
  416.       if (killr0[1] != PrVar[1] /* || Killr0[2] != PrVar[2] */ )
  417.         {
  418.           TCcount++;
  419.           ExtraTime += TCleft;
  420.         }
  421.       if ((abs (score - globalscore) / Sdepth) > ZDELTA)
  422.         {
  423.           TCcount++;
  424.           ExtraTime += TCleft;
  425.         }
  426.     }
  427.       if (score > (Jscore - zwndw) && score > (Tree[1].score + 250)) ExtraTime = 0;
  428. /*printf("sdepth = %d mindepth = %d TCflag = %d \n4*et = %d respt = %d extra = %d\n",Sdepth,MINDEPTH,TCflag,4*et,ResponseTime,ExtraTime);*/
  429.       if (root->flags & exact) flag.timeout = true;
  430.       /*else if (Tree[1].score < -9000) flag.timeout = true;*/
  431.       else if (!(Sdepth < MINDEPTH) && TCflag && ((4 * et) > (2*ResponseTime + ExtraTime))) flag.timeout = true;
  432.       /************************ time control ***********************************/
  433.  
  434.       /* save PV as killer */
  435.       for (i = 1; i <= Sdepth + 1; i++) killr0[i] = PrVar[i];
  436.       if (!flag.timeout) Tscore[0] = score;
  437.       /* if (!flag.timeout) */
  438.       for (i = TrPnt[1]+1; i < TrPnt[2]; i++) if (!pick (i, TrPnt[2] - 1)) break;
  439.       /* if done or nothing good to look at quit */
  440.       if ((root->flags & exact) || (score < -9000)) flag.timeout = true;
  441.       /* find the next best move put below root */
  442. #include "debug13.h"
  443.       if (!flag.timeout)
  444.     {
  445.       /* */
  446. #if !defined NODYNALPHA
  447.       Jscore = (plyscore + score) >> 1;
  448. #endif
  449.       zwndw = 20 + abs (Jscore / 12);
  450.       plyscore = score;
  451.       /* recompute search window */
  452.       beta = score + ((computer == black) ? BBwindow : WBwindow);
  453. #if !defined NODYNALPHA
  454.       alpha = ((Jscore < score) ? Jscore : score) - ((computer == black) ? BAwindow : WAwindow) - zwndw;
  455. #else
  456.       alpha = score - ((computer == black) ? BAwindow : WAwindow);
  457. #endif
  458.     }
  459. #if !defined CHESSTOOL && !defined XBOARD
  460. #ifdef QUIETBACKGROUND
  461.       if (!background)
  462. #endif /* QUIETBACKGROUND */
  463.     ShowResults (score, PrVar, '.');
  464. #ifdef DEBUG41
  465.       debug41 (score, PrVar, '.');
  466. #endif
  467. #endif
  468. #include "debug16.h"
  469.       if (((!PrVar[1])||(!PrVar[2]))&&(!(root->flags & exact))&&(iop != 2)&&(abs(score) < 9000)) /* do not trust this move! */
  470.        {
  471.         if (Sdepth > 2)
  472.          {
  473.           if (earlyflag)
  474.            {
  475.             Sdepth--;
  476.            }
  477.           if (!trying_again)
  478.            { /* this is first bogus move we have seen */
  479.             ResponseTime = ResponseTime << 1;
  480.             ExtraTime += 251;
  481.            }
  482.           else
  483.            { /* this is not 1st bogus move we have seen */
  484.             ExtraTime += 201;
  485.            }
  486.           trying_again = 1;
  487.           flag.timeout = false;
  488.           flag.back = false;
  489.           flag.musttimeout = false;
  490.          }
  491.        }
  492.       else if (trying_again) /* this move is trustworthy, to an extent */
  493.        {
  494.         if ((TCflag && ((4 * et) > (ResponseTime + ExtraTime - 251)))||(root->flags & exact)) 
  495.          flag.timeout = true;
  496.        }
  497.       previous_score = score;
  498.     } /* while !flag.timeout */
  499.   /******************************* end of main loop ***********************************/
  500.   /* background mode */
  501.   if (iop == 2)
  502.    {
  503.     if (!flag.easy)
  504.      {
  505.       Sdepth2 = Sdepth;
  506.       if (Sdepth2 > (GlobalTgtDepth+1))
  507.        Sdepth2--;
  508.      }
  509.     return;
  510.    }
  511. #include "debug4.h"
  512.   if (rpt >= 2)
  513.     {
  514.       root->flags |= draw;
  515.       DRAW = CP[101];        /* Repetition */
  516.     }
  517.   else
  518.     /* if no moves and not in check then draw */
  519.   if ((score == -9999) && !(SqAtakd3 (PieceList[side][0], xside)))
  520.     {
  521.       root->flags |= draw;
  522.       DRAW = CP[87];        /* No moves */
  523.     }
  524.   else if (GameCnt == MAXMOVES)
  525.     {
  526.       root->flags |= draw;
  527.       DRAW = CP[80];        /* Max Moves */
  528.     }
  529.   /* not in book so set hint to guessed move for other side */
  530.   if (!bookflag)
  531.     hint = ((PrVar[1]) ? PrVar[2] : 0);
  532.  
  533.   /* if not mate or draw make move and output it */
  534.   if (((score > -9999) && (rpt <= 2)) || (root->flags & draw))
  535.     {
  536.       MakeMove (side, &Tree[0], &tempb, &tempc, &tempsf, &tempst, &INCscore);
  537. #if !defined NOMATERIAL
  538.       if (flag.material && !pmtl[black] && !pmtl[white] && (mtl[white] < (valueR + valueK)) && (mtl[black] < (valueR + valueK)))
  539.     {
  540.       root->flags |= draw;
  541.       DRAW = CP[224];    /* No pieces */
  542.     }
  543.       else
  544. #endif
  545.       if (!PieceCnt[black] && !PieceCnt[white])
  546.     {
  547.       root->flags |= draw;
  548.       DRAW = CP[88];    /* No pieces */
  549.     }
  550.       algbr (root->f, root->t, (short) root->flags);
  551.     }
  552.   else
  553.     {
  554.       algbr (0, 0, 0);        /* Zero move string when mate. */
  555.       root->score = score;    /* When mate, ignore distinctions!
  556.                  * --SMC */
  557.     }
  558.   g = &GameList[GameCnt];
  559.   if (g->flags & capture && g->piece == king)
  560.     {
  561.       flag.mate = flag.illegal = true;
  562.     }
  563.   /* If Time Control get the elapsed time */
  564.   if (TCflag)
  565.     ElapsedTime (1);
  566.   OutputMove (mystr);
  567.   /* if mate set flag */
  568.   if ((score == -9999 || score == 9998))
  569.     flag.mate = true;
  570.   /* if mate clear hint */
  571.   if (flag.mate)
  572.     hint = 0;
  573.   /* if pawn move or capture or castle or promote zero repitition array */
  574.   if ((board[root->t] == pawn) || (root->flags & (capture | cstlmask | promote)))
  575.     {
  576.       Game50 = GameCnt;
  577.       ZeroRPT ();
  578.     }
  579.   /* add move to game list */
  580.   g->score = score;
  581.   g->nodes = NodeCnt;
  582.   g->time = (et +50)/100;
  583.   g->depth = Sdepth;
  584. #include "debug40.h"
  585.   /* update time comtrol info */
  586.   if (TCflag)
  587.     {
  588. #if defined CHESSTOOL || defined XBOARD
  589.       TimeControl.clock[side] -= (et + OperatorTime + 45);
  590.       timecomp[compptr] = (et + OperatorTime + 45);
  591. #else
  592.       TimeControl.clock[side] -= (et + OperatorTime);
  593.       timecomp[compptr] = (et + OperatorTime);
  594. #endif
  595.       /* finished our required moves - setup the next set */
  596.       --TimeControl.moves[side];
  597.     }
  598.   /* check for end conditions */
  599.   if ((root->flags & draw) /* && flag.bothsides */ )
  600. #if !defined CLIENT
  601.      flag.mate = true;
  602. #else 
  603.     ;
  604. #endif
  605.   else if (GameCnt == MAXMOVES)
  606.     {
  607.       flag.mate = true;
  608.     }
  609.   /* out of move store, you loose */
  610.   else
  611.     /* switch to other side */
  612.     player = xside;
  613.   Sdepth = 0;
  614. }
  615.  
  616. int
  617. search (short int side,
  618.     register short int ply,
  619.     register short int depth,
  620.     short int alpha,
  621.     short int beta,
  622.     short unsigned int *bstline,
  623.     short int *rpt)
  624.  
  625. /*
  626.  * Perform an alpha-beta search to determine the score for the current board
  627.  * position. If depth <= 0 only capturing moves, pawn promotions and
  628.  * responses to check are generated and searched, otherwise all moves are
  629.  * processed. The search depth is modified for check evasions, certain
  630.  * re-captures and threats. Extensions may continue for up to 11 ply beyond
  631.  * the nominal search depth.
  632.  */
  633.  
  634.  
  635. {
  636.   register short j, pnt;
  637.   short tempb, tempc, tempsf, tempst;
  638.   short xside, pbst, score, rcnt, InChk;
  639.   unsigned short mv, nxtline[MAXDEPTH];
  640.   struct leaf *node, tmp;
  641.   short best = -12000;
  642.   short bestwidth = 0;
  643. #ifdef NULLMOVE
  644. #ifndef AMIGA
  645.   short int PVsave;
  646. #endif
  647.   short int PVarisave;
  648. #endif
  649. #ifdef DEBUG
  650.   int xxxtmp;
  651.   int tracetmp;
  652. #endif
  653.   NodeCnt++;
  654.   /* look every ZNODE nodes for a timeout */
  655.   if (!null && NodeCnt > ETnodes )
  656.     {
  657.       ElapsedTime (2);
  658.       if (flag.back)
  659.     {
  660.       flag.back = false;
  661.       flag.timeout = true;
  662.       flag.musttimeout = false;
  663.     }
  664.       else if (TCflag || MaxResponseTime)
  665.     {
  666.       if ((et >= (ResponseTime + ExtraTime)) && Sdepth > MINDEPTH && abs(best) < 10000)
  667.         {            /* try to extend to finish ply */
  668. #define TRYEXTEND 1
  669. #ifdef TRYEXTEND
  670.           if ((TCflag && TCcount < MAXTCCOUNTX)&&(GameCnt > 29))
  671.         {
  672.           flag.musttimeout = true;
  673.           TCcount += 1;
  674.           ExtraTime += TCleft;
  675.         }
  676.           else
  677.         {
  678.           flag.timeout = true;
  679.           flag.musttimeout = false;
  680.         }
  681. #else
  682.           if ((TCflag && TCcount < MAXTCCOUNTX)&&(flag.easy))
  683.         {
  684.           flag.musttimeout = true;
  685.           TCcount += 1;
  686.           ExtraTime += TCleft;
  687.         }
  688.           else
  689.         {
  690.           flag.timeout = true;
  691.           flag.musttimeout = false;
  692.         }
  693. #endif
  694.         }
  695.     }
  696.     }
  697.   else if (!TCflag && flag.musttimeout && Sdepth > MINDEPTH)
  698.     {
  699.       flag.timeout = true;
  700.       flag.musttimeout = false;
  701.     }
  702.   xside = side ^ 1;
  703.   /* slk is lone king indicator for either side */
  704.   score = evaluate (side, ply, alpha, beta, INCscore, &InChk);
  705.  
  706.   /*
  707.    * check for possible repitition if so call repitition - rpt is
  708.    * repeat count
  709.    */
  710.   if ((ply <= Sdepth + 3) && rpthash[side][hashkey & 0xFF] > 0)
  711.     {
  712.       *rpt = repetition ();
  713.  
  714.       /*
  715.        * repeat position >2 don't need to return score it's taken
  716.        * care of above
  717.        */
  718.       if (*rpt == 1) score /= 2;
  719.     }
  720.   else
  721.     *rpt = 0;
  722.  
  723.   /* score > 9000 its a draw or mate */
  724.   if (score > 9000)
  725.     {
  726.       bstline[ply] = 0;
  727.       return (score);
  728.     }
  729.   /* Do we need to add depth because of special conditions */
  730.   /* if in check or pawn threat or in capture sequence search deeper */
  731.   /*************************************** depth extensions ***********************************/
  732.   if (depth > 0)
  733.     {
  734.       /* Allow opponent a chance to check again */
  735.       if (InChk)
  736.     depth = (depth < 2) ? 2 : depth;
  737.       else if (PawnThreat[ply - 1] ||
  738.            (flag.rcptr && (score > alpha) &&
  739.       (score < beta) && (ply > 2) && CptrFlag[ply - 1] && CptrFlag[ply - 2]))
  740.     ++depth;
  741.     }
  742.   else 
  743.     {
  744.       if (score >= alpha &&
  745.       (InChk || PawnThreat[ply - 1] || (hung[side] > 1 && ply == Sdepth + 1)))
  746.     depth = 1;
  747.       else if (score <= beta &&
  748.            ((ply < Sdepth + 4) && (ply > 4) &&
  749.         ChkFlag[ply - 2] && ChkFlag[ply - 4] &&
  750.         ChkFlag[ply - 2] != ChkFlag[ply - 4]))
  751.     depth = 1;
  752.     }
  753.   /*******************************************************************************************/
  754.   /* try the local transition table if it's there */
  755. #if ttblsz
  756.   if (/*depth > 0 &&*/ flag.hash && ply > 1)
  757.     {
  758.       if (ProbeTTable (side, depth, ply, &alpha, &beta, &score) == true)
  759.     {
  760.       bstline[ply] = PV;
  761.       bstline[ply + 1] = 0;
  762. #include "debug64.h"
  763.       if (beta == -20000)
  764.         return (score);
  765.       if (alpha > beta)
  766.         return (alpha);
  767.     }
  768. #ifdef HASHFILE
  769.       /* ok try the transition file if its there */
  770.       else if (hashfile && (depth > HashDepth) && (GameCnt < HashMoveLimit)
  771.      && (ProbeFTable (side, depth, ply, &alpha, &beta, &score) == true))
  772.     {
  773. #ifdef notdef
  774.       int hgood = false;
  775.       int f = PV >> 8;
  776.       int t = PV & 0x3f;
  777.       register int i;
  778.  
  779.       /*
  780.        * if you find something put it in the local table
  781.        * for future reference
  782.        */
  783.       hgood = false;
  784.       for (i = TrPnt[ply]; i < TrPnt[ply + 1]; i++)
  785.         {
  786.           if (Tree[i].f == f && Tree[i].t == t)
  787.         {
  788.           hgood = true;
  789.           break;
  790.         }
  791.         }
  792.       if (hgood)
  793.         {
  794. #endif
  795.           PutInTTable (side, score, depth, ply, alpha, beta, PV);
  796.           bstline[ply] = PV;
  797.           bstline[ply + 1] = 0;
  798.           if (beta == -20000)
  799.         return (score);
  800.           if (alpha > beta)
  801.         return (alpha);
  802. #ifdef notdef
  803.         }
  804. #endif
  805. #include "debug10.h"
  806.     }
  807. #endif /* HASHFILE */
  808.     }
  809. #endif /* ttblsz */
  810.  
  811.   /*
  812.    * if more then DepthBeyond ply past goal depth or at goal depth and
  813.    * score > beta quit - means we are out of the window
  814.    */
  815.   if (ply > DepthBeyond || (depth < 1 && score > beta))
  816.     {
  817.       return (score);
  818.     }
  819.  
  820.   /*
  821.    * if below first ply and not at goal depth generate all moves else
  822.    * only capture moves
  823.    */
  824.   if (ply > 1)
  825.     if (depth > 0  || ply<(SDEPTHLIM)|| 
  826.     (background && ply<Sdepth + 2))
  827.       {
  828.     MoveList (side, ply);
  829.       }
  830.     else{
  831.       CaptureList (side, ply);
  832.     }
  833.  
  834.   /* no moves return what we have */
  835.  
  836.   /*
  837.    * normally a search will continue til past goal and no more capture
  838.    * moves exist
  839.    */
  840.   /* unless it hits DepthBeyond */
  841.   if (TrPnt[ply] == TrPnt[ply + 1])
  842.     {
  843.       return (score);
  844.     }
  845.  
  846.  
  847.  
  848.   /* if not at goal set best = -inf else current score */
  849.      best = (depth >0)?-12000:score;
  850. #ifdef NULLMOVE
  851.  
  852.   PVarisave = PVari;
  853.   if (!null &&                         /* no previous null-move */
  854.       !PVari &&                        /* no null-move during the PV */
  855.       (ply > 1) &                       /* not at ply 1 */
  856.       (depth > 1) &&                   /* not during the quienscesearch */
  857.       !InChk &&                        /* no check */
  858.       ((mtl[side] + mtl[xside]) > 4000))
  859.     /* enough material such that zugzwang is unlike but who knows which value
  860.        is suitable? */
  861.     {
  862.       
  863.       /* ok, we make a null move, i.e.  this means we have nothing to do
  864.       but we have to keep the some arrays up to date otherwise gnuchess
  865.       gets confused.  Maybe somebody knows exactly which informations are
  866.      important and which not.
  867.  
  868.      Another idea is that we try the null-move first and generate the
  869.      moves later.  This may save time but we have to take care that
  870.      PV and other variables contain the right value so that the move
  871.      ordering works right.
  872.      */
  873.       register struct GameRec *g;
  874.       
  875.       nxtline[ply + 1] = 0;
  876.       CptrFlag[ply] = 0;
  877.       PawnThreat[ply] = 0;
  878.       Tscore[ply] = score;
  879.       /*PVsave = PV;
  880.       PV = 0;*/
  881.       null = 1;
  882.       g = &GameList[++GameCnt];
  883.       g->hashkey = hashkey;
  884.       g->hashbd = hashbd;
  885.       epsquare = -1;
  886.       TOsquare = -1;
  887.       g->Game50 = Game50;
  888. #ifdef LONGINTS
  889.       g->gmove = 0xffffffff;
  890. #else
  891.       g->gmove = 0xffff;
  892. #endif
  893.       g->flags = 0;
  894.       g->piece = 0;
  895.       g->color = neutral;
  896.       
  897.       best = -search(xside, ply+1, depth - 2, -beta-1, -beta, nxtline,&rcnt);
  898.       null = 0;
  899.       /*PV = PVsave;*/
  900.       GameCnt--;
  901.       if (best > beta)
  902.      return (best);
  903.       else
  904.      best = -12000;
  905.     }
  906. #endif
  907.   /* if best so far is better than alpha set alpha to best */
  908.     if(best>alpha)alpha=best;
  909.   /********************** main loop ************************************************************************/
  910.   /* look at each move until no more or beta cutoff */
  911.   for (pnt = pbst = TrPnt[ply]; pnt < TrPnt[ply + 1] && best <= beta; pnt++)
  912.     {
  913.       /* find the most interesting looking of the remaining moves */
  914.       if (ply > 1)
  915.     pick (pnt, TrPnt[ply + 1] - 1);
  916. #ifdef NULLMOVE
  917.       PVari = PVarisave && (pnt == TrPnt[ply]);  /* Is this the PV? */
  918. #endif
  919.  
  920.       node = &Tree[pnt];
  921.       /* is this a forbidden move */
  922.       if (ply == 1 && node->score == -32768)
  923.     continue;
  924. #ifdef DEBUG
  925.     if(debuglevel & (512 | 1024)){
  926.         if(!tracen)traceflag = ((ply >traceply)?false:true);
  927.          else
  928.         if(ply <= tracen && (ply ==1 || traceflag))
  929.             { 
  930.             if(trace[ply] == (Tree[pnt].t |(Tree[pnt].f<<8))) traceflag = true; else traceflag = false; }
  931.         tracelog[ply] = (Tree[pnt].t |(Tree[pnt].f<<8));
  932.         tracelog[ply+1] = 0;
  933. }
  934. #endif
  935.       nxtline[ply + 1] = 0;
  936.  
  937. #if !defined CHESSTOOL && !defined XBOARD
  938.       /* if at top level */
  939.       if (ply == 1)
  940.     {            /* at the top update search status */
  941.       if (flag.post)
  942. #ifdef QUIETBACKGROUND
  943.         if (!background)
  944. #endif /* QUIETBACKGROUND */
  945.           ShowCurrentMove (pnt, node->f, node->t);
  946.     }
  947. #endif
  948.       if (!(node->flags & exact))
  949.     {
  950.       /* make the move and go deeper */
  951.       MakeMove (side, node, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  952.       CptrFlag[ply] = (node->flags & capture);
  953.       PawnThreat[ply] = (node->flags & pwnthrt);
  954.       Tscore[ply] = node->score;
  955.       PV = node->reply;
  956. #ifdef DEBUG
  957.       xxxtmp = node->score;
  958.       tracetmp = traceflag;
  959. #endif
  960.       node->score = -search (xside, ply + 1,
  961.                  (depth > 0)?depth-1:0,
  962.                  -beta, -alpha,
  963.                  nxtline, &rcnt);
  964.       node->width = (ply % 2 == 1) ? (TrPnt[ply + 2] - TrPnt[ply + 1]) : 0;
  965.       if (abs (node->score) > 9000) node->flags |= exact;
  966.       else if (rcnt == 1) node->score /= 2;
  967. #include "debug256.h"
  968.       if ((rcnt >= 2 || GameCnt - Game50 > 99 || (node->score == 9999 - ply && !ChkFlag[ply])))
  969.         {
  970.           node->flags |= (draw | exact);
  971.           DRAW = CP[58];    /* Draw */
  972.           node->score = ((side == computer) ? contempt : -contempt);
  973.         }
  974.       node->reply = nxtline[ply + 1];
  975.       /* reset to try next move */
  976.       UnmakeMove (side, node, &tempb, &tempc, &tempsf, &tempst);
  977.     }
  978.       /* if best move so far */
  979.       if (!flag.timeout && ((node->score > best) || ((node->score == best) && (node->width > bestwidth))))
  980.     {
  981.       /*
  982.        * all things being equal pick the denser part of the
  983.        * tree
  984.        */
  985.       bestwidth = node->width;
  986.  
  987.       /*
  988.        * if not at goal depth and better than alpha and not
  989.        * an exact score increment by depth
  990.        */
  991.       if (depth > 0 && node->score > alpha && !(node->flags & exact))
  992.         node->score += depth;
  993.       best = node->score;
  994.       pbst = pnt;
  995.       if (best > alpha) { alpha = best; }
  996.       /* update best line */
  997.       for (j = ply + 1; nxtline[j] > 0; j++) bstline[j] = nxtline[j];
  998.       bstline[j] = 0;
  999.       bstline[ply] = (node->f << 8) | node->t;
  1000.       /* if at the top */
  1001.       if (ply == 1)
  1002.         {
  1003.           /*
  1004.            * if its better than the root score make it
  1005.            * the root
  1006.            */
  1007.           if ((best > root->score) || ((best == root->score) && (bestwidth > root->width)))
  1008.         {
  1009.           tmp = Tree[pnt];
  1010.           for (j = pnt - 1; j >= 0; j--) Tree[j + 1] = Tree[j];
  1011.           Tree[0] = tmp;
  1012.           pbst = 0;
  1013.         }
  1014. #if !defined CHESSTOOL && !defined XBOARD
  1015. #ifdef QUIETBACKGROUND
  1016.           if (!background)
  1017. #endif /* QUIETBACKGROUND */
  1018.         if (Sdepth > 2)
  1019.           if (best > beta)
  1020.             {
  1021.                       global_tmp_score = best;
  1022.               ShowResults (best, bstline, '+');
  1023. #ifdef DEBUG41
  1024.               debug41 (best, bstline, '+');
  1025. #endif
  1026.             }
  1027.           else if (best < alpha)
  1028.             {
  1029.                       global_tmp_score = best;
  1030.               ShowResults (best, bstline, '-');
  1031. #ifdef DEBUG41
  1032.               debug41 (best, bstline, '-');
  1033. #endif
  1034.             }
  1035.           else
  1036.                    {
  1037.                     global_tmp_score = best;
  1038.             ShowResults (best, bstline, '&');
  1039.                    }
  1040. #ifdef DEBUG41
  1041.           debug41 (best, bstline, '&');
  1042. #endif
  1043. #else
  1044.        if(!background && Sdepth >2 && best < alpha){
  1045.         ExtraTime=8*TCleft;
  1046.        }
  1047. #endif
  1048.         }
  1049.     }
  1050.       if (flag.timeout)
  1051.     {
  1052.       return (Tscore[ply - 1]);
  1053.     }
  1054.     }
  1055.  
  1056.   /******************************************************************************************/
  1057.   node = &Tree[pbst];
  1058.   mv = (node->f << 8) | node->t;
  1059. #ifdef NULLMOVE
  1060.   PVari = PVarisave;
  1061. #endif
  1062. #ifdef DEBUG
  1063. #include "debug512.h"
  1064. #endif
  1065.  
  1066.   /*
  1067.    * we have a move so put it in local table - if it's already there
  1068.    * done else if not there or needs to be updated also put it in
  1069.    * hashfile
  1070.    */
  1071. #if ttblsz
  1072.   if (flag.hash && ply <= Sdepth && *rpt == 0 && best == alpha)
  1073.     {
  1074. #ifdef notdef
  1075. algbr(node->f,node->t,0);
  1076. printf("IN-> %lx %lx %d %d %s\n",hashkey,hashbd,depth,side,mvstr[0]);
  1077. #endif
  1078.       if (PutInTTable (side, best, depth, ply, alpha, beta, mv)
  1079. #ifdef HASHFILE
  1080.       && hashfile && (depth > HashDepth) && (GameCnt < HashMoveLimit))
  1081.     {
  1082. #ifdef notdef
  1083. printf("FT %d %d %d %x\n",side,best,depth,mv);
  1084. #endif
  1085.       PutInFTable (side, best, depth, ply, alpha, beta, node->f, node->t);
  1086.     }
  1087. #else
  1088.     );
  1089. #endif /* HASHFILE */
  1090.     }
  1091. #endif /* ttblsz */
  1092.   if (depth > 0)
  1093.     {
  1094. #ifdef HISTORY
  1095.       j = (node->f << 6) | node->t;
  1096.       if (side == black)
  1097.     j |= 0x4000;
  1098. /*TMPif (j > 32767) { printf("\nBAD HISTORY GUY BAD BAD BAD!!\n");getchar(); }*/
  1099.       if (history[j] < HISTORYLIM)
  1100.     history[j] += (unsigned short) 1<<depth;
  1101. #endif
  1102.       if (node->t != (short)(GameList[GameCnt].gmove & 0xFF))
  1103.     if (best <= beta)
  1104.       killr3[ply] = mv;
  1105.     else if (mv != killr1[ply])
  1106.       {
  1107.         killr2[ply] = killr1[ply];
  1108.         killr1[ply] = mv;
  1109.       }
  1110.       killr0[ply] = ((best > 9000) ? mv : 0);
  1111.     }
  1112.   return (best);
  1113. }
  1114.  
  1115.  
  1116.  
  1117.  
  1118. int
  1119. castle (short int side, short int kf, short int kt, short int iop)
  1120.  
  1121. /* Make or Unmake a castling move. */
  1122.  
  1123. {
  1124.   register short rf, rt, t0, xside;
  1125.  
  1126.   xside = side ^ 1;
  1127.   if (kt > kf)
  1128.     {
  1129.       rf = kf + 3;
  1130.       rt = kt - 1;
  1131.     }
  1132.   else
  1133.     {
  1134.       rf = kf - 4;
  1135.       rt = kt + 1;
  1136.     }
  1137.   if (iop == 0)
  1138.     {
  1139.       if (kf != kingP[side] ||
  1140.       board[kf] != king ||
  1141.       board[rf] != rook ||
  1142.       color[kf] != side ||
  1143.       color[rf] != side ||
  1144.       Mvboard[kf] != 0 ||
  1145.       Mvboard[rf] != 0 ||
  1146.       color[kt] != neutral ||
  1147.       color[rt] != neutral ||
  1148.       color[kt - 1] != neutral ||
  1149.       SqAtakd3 (kf, xside) ||
  1150.       SqAtakd3 (kt, xside) ||
  1151.       SqAtakd3 (rt, xside))
  1152.     return (false);
  1153.     }
  1154.   else
  1155.     {
  1156.       if (iop == 1)
  1157.     {
  1158.           Castled[side] = 1;
  1159.       castld[side] = true;
  1160.       Mvboard[kf]++;
  1161.       Mvboard[rf]++;
  1162.     }
  1163.       else
  1164.     {
  1165.           Castled[side] = 0;
  1166.       castld[side] = false;
  1167.       Mvboard[kf]--;
  1168.       Mvboard[rf]--;
  1169.       t0 = kt;
  1170.       kt = kf;
  1171.       kf = t0;
  1172.       t0 = rt;
  1173.       rt = rf;
  1174.       rf = t0;
  1175.     }
  1176.       board[kt] = king;
  1177.       color[rt] = color[kt] = side;
  1178.       Pindex[kt] = 0;
  1179.       board[kf] = no_piece;
  1180.       color[rf] = color[kf] = neutral;
  1181.       board[rt] = rook;
  1182.       Pindex[rt] = Pindex[rf];
  1183.       board[rf] = no_piece;
  1184.       PieceList[side][Pindex[kt]] = kt;
  1185.       PieceList[side][Pindex[rt]] = rt;
  1186.       UpdateHashbd (side, king, kf, kt);
  1187.       UpdateHashbd (side, rook, rf, rt);
  1188.     }
  1189.   return (true);
  1190. }
  1191.  
  1192.  
  1193. void
  1194. EnPassant (short int xside, short int f, short int t, short int iop)
  1195.  
  1196. /*
  1197.  * Make or unmake an en passant move.
  1198.  */
  1199.  
  1200. {
  1201.   register short l;
  1202.  
  1203.   l = t + ((t > f) ? -8 : 8);
  1204.   if (iop == 1)
  1205.     {
  1206.       myEnPassant[xside] = 1;
  1207.       board[l] = no_piece;
  1208.       color[l] = neutral;
  1209.     }
  1210.   else
  1211.     {
  1212.       board[l] = pawn;
  1213.       color[l] = xside;
  1214.       myEnPassant[xside] = 0;
  1215.     }
  1216.   InitializeStats ();
  1217. }
  1218.  
  1219.  
  1220. void
  1221. UpdatePieceList (short int side, short int sq, short int iop)
  1222.  
  1223. /*
  1224.  * Update the PieceList and Pindex arrays when a piece is captured or when a
  1225.  * capture is unmade.
  1226.  */
  1227.  
  1228. {
  1229.   register short i;
  1230.  
  1231.   if (iop == 1)
  1232.     {
  1233.       PieceCnt[side]--;
  1234.       for (i = Pindex[sq]; i <= PieceCnt[side]; i++)
  1235.     {
  1236.       PieceList[side][i] = PieceList[side][i + 1];
  1237.       Pindex[PieceList[side][i]] = i;
  1238.     }
  1239.     }
  1240.   else
  1241.     {
  1242.       PieceCnt[side]++;
  1243.       PieceList[side][PieceCnt[side]] = sq;
  1244.       Pindex[sq] = PieceCnt[side];
  1245.     }
  1246. }
  1247.  
  1248. void
  1249. MakeMove (short int side,
  1250.       struct leaf *node,
  1251.       short int *tempb,    /* color of to square */
  1252.       short int *tempc,    /* piece at to square */
  1253.       short int *tempsf,    /* static value of piece on from */
  1254.       short int *tempst,    /* static value of piece on to */
  1255.       short int *INCscore)    /* score increment for pawn structure change */
  1256.  
  1257. /*
  1258.  * Update Arrays board[], color[], and Pindex[] to reflect the new board
  1259.  * position obtained after making the move pointed to by node. Also update
  1260.  * miscellaneous stuff that changes when a move is made.
  1261.  */
  1262.  
  1263. {
  1264.   register short f, t, xside, ct, cf;
  1265.   register struct GameRec *g;
  1266.  
  1267.   xside = side ^ 1;
  1268.   g = &GameList[++GameCnt];
  1269.   g->hashkey = hashkey;
  1270.   g->hashbd = hashbd;
  1271.   g->epssq = epsquare;
  1272.   f = node->f;
  1273.   t = node->t;
  1274.   epsquare = -1;
  1275.   /* FROMsquare = f;*/
  1276.   TOsquare = t;
  1277.   *INCscore = 0;
  1278.   g->Game50 = Game50;
  1279.   g->gmove = (f << 8) | t;
  1280.   g->flags = node->flags;
  1281.   if (node->flags & cstlmask)
  1282.     {
  1283.       g->piece = no_piece;
  1284.       g->color = side;
  1285.       (void) castle (side, f, t, 1);
  1286.       Game50 = GameCnt;
  1287.     }
  1288.   else
  1289.     {
  1290.       if (!(node->flags & capture) && (board[f] != pawn))
  1291.     {rpthash[side][hashkey & 0xFF]++;ISZERO++;}
  1292.       else
  1293.     Game50 = GameCnt;
  1294.       *tempsf = svalue[f];
  1295.       *tempst = svalue[t];
  1296.       g->piece = *tempb = board[t];
  1297.       g->color = *tempc = color[t];
  1298.       if (*tempc != neutral)
  1299.     {
  1300.       UpdatePieceList (*tempc, t, 1);
  1301.       /* if capture decrement pawn count */
  1302.       if (*tempb == pawn)
  1303.         {
  1304.           --PawnCnt[*tempc][column (t)];
  1305.         }
  1306.       if (board[f] == pawn)
  1307.         {
  1308.           cf = column (f);
  1309.           ct = column (t);
  1310.           /* move count from from to to */
  1311.           --PawnCnt[side][cf];
  1312.           ++PawnCnt[side][ct];
  1313.  
  1314.           /*
  1315.            * calculate increment for pawn structure
  1316.            * changes
  1317.            */
  1318.           /* doubled or more - */
  1319.           if (PawnCnt[side][ct] > (1 + PawnCnt[side][cf]))
  1320.         *INCscore -= 15;
  1321.           /* went to empty column + */
  1322.           else if (PawnCnt[side][ct] < 1 + PawnCnt[side][cf])
  1323.         *INCscore += 15;
  1324.  
  1325.           /*
  1326.            * went to outside col or empty col on one
  1327.            * side ????????
  1328.            */
  1329.           else if (ct == 0 || ct == 7 || PawnCnt[side][ct + ct - cf] == 0)
  1330.         *INCscore -= 15;
  1331.         }
  1332.       mtl[xside] -= value[*tempb];
  1333.       if (*tempb == pawn)
  1334.         pmtl[xside] -= valueP;
  1335.       UpdateHashbd (xside, *tempb, -1, t);
  1336.       *INCscore += *tempst;
  1337.       Mvboard[t]++;
  1338.     }
  1339.       color[t] = color[f];
  1340.       board[t] = board[f];
  1341.       svalue[t] = svalue[f];
  1342.       Pindex[t] = Pindex[f];
  1343.       PieceList[side][Pindex[t]] = t;
  1344.       color[f] = neutral;
  1345.       board[f] = no_piece;
  1346.       if (board[t] == pawn)
  1347.     if (t - f == 16)
  1348.       epsquare = f + 8;
  1349.     else if (f - t == 16)
  1350.       epsquare = f - 8;
  1351.       if (node->flags & promote)
  1352.     {
  1353.       board[t] = node->flags & pmask;
  1354.       if (board[t] == queen)
  1355.         HasQueen[side]++;
  1356.       else if (board[t] == rook)
  1357.         HasRook[side]++;
  1358.       else if (board[t] == bishop)
  1359.         HasBishop[side]++;
  1360.       else if (board[t] == knight)
  1361.         HasKnight[side]++;
  1362.       --PawnCnt[side][column (t)];
  1363.       mtl[side] += value[board[t]] - valueP;
  1364.       pmtl[side] -= valueP;
  1365.       UpdateHashbd (side, pawn, f, -1);
  1366.       UpdateHashbd (side, board[t], f, -1);
  1367.       *INCscore -= *tempsf;
  1368.     }
  1369.       if (node->flags & epmask)
  1370.     EnPassant (xside, f, t, 1);
  1371.       else
  1372.     UpdateHashbd (side, board[t], f, t);
  1373.       Mvboard[f]++;
  1374.     }
  1375. }
  1376.  
  1377. void
  1378. UnmakeMove (short int side,
  1379.         struct leaf *node,
  1380.         short int *tempb,
  1381.         short int *tempc,
  1382.         short int *tempsf,
  1383.         short int *tempst)
  1384.  
  1385. /*
  1386.  * Take back a move.
  1387.  */
  1388.  
  1389. {
  1390.   register short f, t, xside;
  1391.  
  1392.   xside = side ^ 1;
  1393.   f = node->f;
  1394.   t = node->t;
  1395.   Game50 = GameList[GameCnt].Game50;
  1396.   if (node->flags & cstlmask)
  1397.     (void) castle (side, f, t, 2);
  1398.   else
  1399.     {
  1400.       color[f] = color[t];
  1401.       board[f] = board[t];
  1402.       svalue[f] = *tempsf;
  1403.       Pindex[f] = Pindex[t];
  1404.       PieceList[side][Pindex[f]] = f;
  1405.       color[t] = *tempc;
  1406.       board[t] = *tempb;
  1407.       svalue[t] = *tempst;
  1408.       if (node->flags & promote)
  1409.     {
  1410.       board[f] = pawn;
  1411.       ++PawnCnt[side][column (t)];
  1412.       mtl[side] += valueP - value[node->flags & pmask];
  1413.       pmtl[side] += valueP;
  1414.       UpdateHashbd (side, (short) node->flags & pmask, -1, t);
  1415.       UpdateHashbd (side, pawn, -1, t);
  1416.     }
  1417.       if (*tempc != neutral)
  1418.     {
  1419.       UpdatePieceList (*tempc, t, 2);
  1420.       if (*tempb == pawn)
  1421.         {
  1422.           ++PawnCnt[*tempc][column (t)];
  1423.         }
  1424.       if (board[f] == pawn)
  1425.         {
  1426.           --PawnCnt[side][column (t)];
  1427.           ++PawnCnt[side][column (f)];
  1428.         }
  1429.       mtl[xside] += value[*tempb];
  1430.       if (*tempb == pawn)
  1431.         pmtl[xside] += valueP;
  1432.       UpdateHashbd (xside, *tempb, -1, t);
  1433.       Mvboard[t]--;
  1434.     }
  1435.       if (node->flags & epmask)
  1436.     {
  1437.       EnPassant (xside, f, t, 2);
  1438.     }
  1439.       else
  1440.     UpdateHashbd (side, board[f], f, t);
  1441.       Mvboard[f]--;
  1442.       if (!(node->flags & capture) && (board[f] != pawn))
  1443.     {rpthash[side][hashkey & 0xFF]--;ISZERO--;}
  1444.     }
  1445.   epsquare = GameList[GameCnt--].epssq;
  1446. }
  1447.  
  1448.  
  1449. void
  1450. InitializeStats (void)
  1451.  
  1452. /*
  1453.  * Scan thru the board seeing what's on each square. If a piece is found,
  1454.  * update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also
  1455.  * determine the material for each side and set the hashkey and hashbd
  1456.  * variables to represent the current board position. Array
  1457.  * PieceList[side][indx] contains the location of all the pieces of either
  1458.  * side. Array Pindex[sq] contains the indx into PieceList for a given
  1459.  * square.
  1460.  */
  1461.  
  1462. {
  1463.   register short i, sq;
  1464.  
  1465.   epsquare = -1;
  1466.   for (i = 0; i < 8; i++)
  1467.     {
  1468.       PawnCnt[white][i] = PawnCnt[black][i] = 0;
  1469.     }
  1470.   mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0;
  1471.   PieceCnt[white] = PieceCnt[black] = 0;
  1472.   hashbd = hashkey = 0;
  1473.   for (sq = 0; sq < 64; sq++)
  1474.     if (color[sq] != neutral)
  1475.       {
  1476.     mtl[color[sq]] += value[board[sq]];
  1477.     if (board[sq] == pawn)
  1478.       {
  1479.         pmtl[color[sq]] += valueP;
  1480.         ++PawnCnt[color[sq]][column (sq)];
  1481.       }
  1482.     Pindex[sq] = ((board[sq] == king) ? 0 : ++PieceCnt[color[sq]]);
  1483.  
  1484.     PieceList[color[sq]][Pindex[sq]] = sq;
  1485.     hashbd ^= hashcode[color[sq]][board[sq]][sq].bd;
  1486.     hashkey ^= hashcode[color[sq]][board[sq]][sq].key;
  1487.       }
  1488. }
  1489.